﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using LowLevelGraphics;

namespace ImageRecognition2
{
    /// <summary>
    /// Segmentator
    /// </summary>
    public class Segmentator
    {
        UnsafeBitmap m_Bitmap = null;
        int m_r = 0;
        int m_g = 0;
        int m_b = 0;
        
        /// <summary>
        /// Segmentator, constructor
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="r"></param>
        /// <param name="g"></param>
        /// <param name="b"></param>
        public Segmentator(UnsafeBitmap bitmap, int r, int g, int b)
        {
            m_Bitmap = bitmap;
            m_r = r;
            m_g = g;
            m_b = b;
        }

        //TODO: relativen modus hinzufügen

        //TODO: als Scanline blob Extraktor algorithmus benutzen,
        //dazu müssen nur die Scanlines mit ähnlichen Durchschnittsfarben die sich berühren,
        //gemerged werden. Interessante Frage dazu: Regions oder Rectangles benutzen?
        //Regions sind eigentlich besser, da beliebige Formen entstehen können.

        /// <summary>
        /// This is a fast color segmentation on a horizontal line base
        /// </summary>
        /// <remarks>Interesting feature to add: relative color tolerance from previous pixel
        /// Maybe I should also add a vertical mode?
        /// And what might happen if both is combined?</remarks>
        public void FastSegmentation()
        {
            UnsafeBitmap _bitmap = m_Bitmap;
            List<List<Range>> aScanLine = new List<List<Range>>();

            List<Color> aColor = new List<Color>();
            aColor.Add(_bitmap.GetPixel(0, 0));

            int nCount = 1;
            int x = 0; int y = 0;

            //1st pass

            int nHeight = _bitmap.Height;
            int nWidth = _bitmap.Width;
            for (y = 0; y < nHeight; y++)
            {
                List<Range> aList = new List<Range>();
                aColor.Add(_bitmap.GetPixel(0, y));
                nCount = 1;

                for (x = 0; x < nWidth - 1; x++)
                {
                    Color colorStart = _bitmap.GetPixel(x, y);
                    x++;
                    Color colorNext = _bitmap.GetPixel(x, y);

                    int nStartX = 0;
                    int nEndX = 0;

                    //Found something interesting?
                    if (ColorFunctions.IsInColorTolerance(colorStart, colorNext, m_r, m_g, m_b))
                    {
                        //if so, remember position and search for the end of the interesting pixel formation
                        nStartX = x;
                        while (ColorFunctions.IsInColorTolerance(colorStart, colorNext, m_r, m_g, m_b))
                        {
                            colorNext = _bitmap.GetPixel(x, y);
                            aColor.Add(colorNext);
                            x++;
                            if (x >= _bitmap.Width)
                            {
                                break;
                            }
                            nCount++;
                        }

                        //end found? then calculate average color and add this range to the scanlines 
                        nEndX = x;
                        Color colorAvg = ColorFunctions.AverageColor(aColor);
                        aColor.Clear();

                        Range range = new Range(nStartX, nEndX, y, colorAvg);
                        aList.Add(range);
                    }
                    nCount++;
                }
                aScanLine.Add(aList);
            }

            _bitmap.Dispose();
            //Replace values by new Colors (the colors have been derived from scanning
            //in the previous loop
            Graphics graphics = Graphics.FromImage(_bitmap.InternalBitmap);
            int nScanLineCount = aScanLine.Count;
            for (y = 0; y < nScanLineCount; y++)
            {
                List<Range> aRange = (List<Range>)aScanLine[y];
                foreach (Range range in aRange)
                {
                    graphics.DrawLine(new Pen(range.Color), range.StartX, y, range.EndX, y);
                }
            }

            JoinRanges(aScanLine, nScanLineCount);
        }

        //TODO: Segmentator, JoinRanges
        /// <summary>
        /// 
        /// </summary>
        /// <param name="aScanLine"></param>
        /// <param name="nScanLineCount"></param>
        private static void JoinRanges(List<List<Range>> aScanLine, int nScanLineCount)
        {
            List<Range> aRangeLine1 = null;
            List<Range> aRangeLine2 = null;
            Region region = new Region();

            GraphicsPath p = new GraphicsPath();
        }
    }
}
